package com.starsea.book.ui.newpage.normalview.delegate

import android.content.Context
import android.content.res.ColorStateList
import android.content.res.TypedArray
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.RippleDrawable
import android.graphics.drawable.StateListDrawable
import android.os.Build
import android.util.AttributeSet
import android.view.View
import android.widget.CompoundButton
import android.widget.EditText
import com.starsea.book.R

/**
 * @author Lee
 * @createTime 2023-07-27 17 GMT+8
 * @desc :
 */
open class RadiusViewDelegate(view: View, context: Context, attrs: AttributeSet?) {
  @JvmField
  protected var mTypedArray: TypedArray

  @JvmField
  protected var mView: View?
  private val mContext: Context
  private val mBackground = GradientDrawable()
  private val mBackgroundPressed = GradientDrawable()
  private val mBackgroundDisabled = GradientDrawable()
  private val mBackgroundSelected = GradientDrawable()
  private val mBackgroundChecked = GradientDrawable()

  //以下为xml属性对应解析参数
  private var mBackgroundColor = 0
  private var mBackgroundPressedColor = 0
  private var mBackgroundDisabledColor = 0
  private var mBackgroundSelectedColor = 0
  private var mBackgroundCheckedColor = 0
  private var mStrokeColor = 0
  private var mStrokePressedColor = 0
  private var mStrokeDisabledColor = 0
  private var mStrokeSelectedColor = 0
  private var mStrokeCheckedColor = 0
  private var mStrokeWidth = 0
  private var mStrokeDashWidth = 0f
  private var mStrokeDashGap = 0f
  var radiusHalfHeightEnable = false
    private set
  var widthHeightEqualEnable = false
    private set
  var radius = 0f
    private set
  private var mTopLeftRadius = 0f
  private var mTopRightRadius = 0f
  private var mBottomLeftRadius = 0f
  private var mBottomRightRadius = 0f
  private var mRippleColor = 0
  private var mRippleEnable = false
  private var mSelected = false
  private var mEnterFadeDuration = 0
  private var mExitFadeDuration = 0

  //以上为xml属性对应解析参数
  @JvmField
  protected var mStateChecked = android.R.attr.state_checked

  @JvmField
  protected var mStateSelected = android.R.attr.state_selected

  @JvmField
  protected var mStatePressed = android.R.attr.state_pressed

  @JvmField
  protected var mStateDisabled = -android.R.attr.state_enabled
  private val mRadiusArr = FloatArray(8)
  private val mStateDrawable = StateListDrawable()
  private var mOnSelectedChangeListener: OnSelectedChangeListener? = null

  interface OnSelectedChangeListener {
    /**
     * Called when the checked state of a View has changed.
     *
     * @param view       The View whose state has changed.
     * @param isSelected The new selected state of buttonView.
     */
    fun onSelectedChanged(view: View?, isSelected: Boolean)
  }

  init {
    mView = view
    mContext = context
    mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RadiusSwitch)
    initAttributes(context, attrs)
    if (view !is CompoundButton && !view.isClickable) {
      view.isClickable = mRippleEnable
    }
    view.isSelected = mSelected
    setSelected(mSelected)
  }

  protected open fun initAttributes(context: Context?, attrs: AttributeSet?) {
    mBackgroundColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_backgroundColor,
      Int.MAX_VALUE
    )
    mBackgroundPressedColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_backgroundPressedColor,
      mBackgroundColor
    )
    mBackgroundDisabledColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_backgroundDisabledColor,
      mBackgroundColor
    )
    mBackgroundSelectedColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_backgroundSelectedColor,
      mBackgroundColor
    )
    mBackgroundCheckedColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_backgroundCheckedColor,
      mBackgroundColor
    )
    mStrokeColor =
      mTypedArray.getColor(R.styleable.RadiusSwitch_rv_strokeColor, Color.GRAY)
    mStrokePressedColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_strokePressedColor,
      mStrokeColor
    )
    mStrokeDisabledColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_strokeDisabledColor,
      mStrokeColor
    )
    mStrokeSelectedColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_strokeSelectedColor,
      mStrokeColor
    )
    mStrokeCheckedColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_strokeCheckedColor,
      mStrokeColor
    )
    mStrokeWidth = mTypedArray.getDimensionPixelSize(
      R.styleable.RadiusSwitch_rv_strokeWidth,
      0
    )
    mStrokeDashWidth =
      mTypedArray.getDimension(R.styleable.RadiusSwitch_rv_strokeDashWidth, 0f)
    mStrokeDashGap =
      mTypedArray.getDimension(R.styleable.RadiusSwitch_rv_strokeDashGap, 0f)
    radiusHalfHeightEnable = mTypedArray.getBoolean(
      R.styleable.RadiusSwitch_rv_radiusHalfHeightEnable,
      false
    )
    widthHeightEqualEnable = mTypedArray.getBoolean(
      R.styleable.RadiusSwitch_rv_widthHeightEqualEnable,
      false
    )
    radius = mTypedArray.getDimension(R.styleable.RadiusSwitch_rv_radius, 0f)
    mTopLeftRadius =
      mTypedArray.getDimension(R.styleable.RadiusSwitch_rv_topLeftRadius, 0f)
    mTopRightRadius =
      mTypedArray.getDimension(R.styleable.RadiusSwitch_rv_topRightRadius, 0f)
    mBottomLeftRadius = mTypedArray.getDimension(
      R.styleable.RadiusSwitch_rv_bottomLeftRadius,
      0f
    )
    mBottomRightRadius = mTypedArray.getDimension(
      R.styleable.RadiusSwitch_rv_bottomRightRadius,
      0f
    )
    mRippleColor = mTypedArray.getColor(
      R.styleable.RadiusSwitch_rv_rippleColor,
      mContext.resources.getColor(R.color.colorRadiusDefaultRipple)
    )
    mRippleEnable = mTypedArray.getBoolean(
      R.styleable.RadiusSwitch_rv_rippleEnable,
      defaultRippleEnable
    )
    mSelected =
      mTypedArray.getBoolean(R.styleable.RadiusSwitch_rv_selected, false)
    mEnterFadeDuration =
      mTypedArray.getInteger(R.styleable.RadiusSwitch_rv_enterFadeDuration, 0)
    mExitFadeDuration =
      mTypedArray.getInteger(R.styleable.RadiusSwitch_rv_exitFadeDuration, 0)
    mTypedArray.recycle()
  }

  /**
   * 是否默认开启水波纹
   *
   * @return
   */
  private val defaultRippleEnable: Boolean
    private get() = mView !is CompoundButton && mView !is EditText

  /**
   * 设置常态背景色
   *
   * @param color
   * @return
   */
  fun setBackgroundColor(color: Int): RadiusViewDelegate {
    mBackgroundColor = color
    return this
  }

  /**
   * 设置按下状态背景色
   *
   * @param color
   * @return
   */
  fun setBackgroundPressedColor(color: Int): RadiusViewDelegate {
    mBackgroundPressedColor = color
    return this
  }

  /**
   * 设置不可操作状态下背景色
   *
   * @param color
   * @return
   */
  fun setBackgroundDisabledColor(color: Int): RadiusViewDelegate {
    mBackgroundDisabledColor = color
    return this
  }

  /**
   * 设置selected状态下背景色
   *
   * @param color
   * @return
   */
  fun setBackgroundSelectedColor(color: Int): RadiusViewDelegate {
    mBackgroundSelectedColor = color
    return this
  }

  /**
   * 设置checked状态背景色
   *
   * @param color
   * @return
   */
  fun setBackgroundCheckedColor(color: Int): RadiusViewDelegate {
    mBackgroundCheckedColor = color
    return this
  }

  /**
   * 设置边框线常态颜色
   *
   * @param strokeColor
   * @return
   */
  fun setStrokeColor(strokeColor: Int): RadiusViewDelegate {
    mStrokeColor = strokeColor
    return this
  }

  /**
   * 设置边框线按下状态颜色
   *
   * @param strokePressedColor
   * @return
   */
  fun setStrokePressedColor(strokePressedColor: Int): RadiusViewDelegate {
    mStrokePressedColor = strokePressedColor
    return this
  }

  /**
   * 设置边框线不可点击状态下颜色
   *
   * @param strokeDisabledColor
   * @return
   */
  fun setStrokeDisabledColor(strokeDisabledColor: Int): RadiusViewDelegate {
    mStrokeDisabledColor = strokeDisabledColor
    return this
  }

  /**
   * 设置边框线selected状态颜色
   *
   * @param strokeSelectedColor
   * @return
   */
  fun setStrokeSelectedColor(strokeSelectedColor: Int): RadiusViewDelegate {
    mStrokeSelectedColor = strokeSelectedColor
    return this
  }

  /**
   * 设置边框checked状态颜色
   *
   * @param strokeCheckedColor
   * @return
   */
  fun setStrokeCheckedColor(strokeCheckedColor: Int): RadiusViewDelegate {
    mStrokeCheckedColor = strokeCheckedColor
    return this
  }

  /**
   * 设置边框线宽度(粗细)
   *
   * @param strokeWidth
   * @return
   */
  fun setStrokeWidth(strokeWidth: Int): RadiusViewDelegate {
    mStrokeWidth = strokeWidth
    return this
  }

  /**
   * 设置虚线宽度
   *
   * @param strokeDashWidth
   * @return
   */
  fun setStrokeDashWidth(strokeDashWidth: Float): RadiusViewDelegate {
    mStrokeDashWidth = strokeDashWidth
    return this
  }

  /**
   * 设置虚线间隔
   *
   * @param strokeDashGap
   * @return
   */
  fun setStrokeDashGap(strokeDashGap: Float): RadiusViewDelegate {
    mStrokeDashGap = strokeDashGap
    return this
  }

  /**
   * 设置半高度圆角
   *
   * @param enable
   * @return
   */
  fun setRadiusHalfHeightEnable(enable: Boolean): RadiusViewDelegate {
    radiusHalfHeightEnable = enable
    return this
  }

  /**
   * 设置宽高相等
   *
   * @param enable
   * @return
   */
  fun setWidthHeightEqualEnable(enable: Boolean): RadiusViewDelegate {
    widthHeightEqualEnable = enable
    return this
  }

  /**
   * 设置整体圆角弧度
   *
   * @param radius
   * @return
   */
  fun setRadius(radius: Float): RadiusViewDelegate {
    this.radius = radius
    return this
  }

  /**
   * 设置左上圆角
   *
   * @param radius
   * @return
   */
  fun setTopLeftRadius(radius: Float): RadiusViewDelegate {
    mTopLeftRadius = radius
    return this
  }

  /**
   * 设置右上圆角
   *
   * @param radius
   * @return
   */
  fun setTopRightRadius(radius: Float): RadiusViewDelegate {
    mTopRightRadius = radius
    return this
  }

  /**
   * 设置左下圆角
   *
   * @param radius
   * @return
   */
  fun setBottomLeftRadius(radius: Float): RadiusViewDelegate {
    mBottomLeftRadius = radius
    return this
  }

  /**
   * 设置右下圆角
   *
   * @param radius
   * @return
   */
  fun setBottomRightRadius(radius: Float): RadiusViewDelegate {
    mBottomRightRadius = radius
    return this
  }

  /**
   * 设置水波纹颜色 5.0以上支持
   *
   * @param color
   * @return
   */
  fun setRippleColor(color: Int): RadiusViewDelegate {
    mRippleColor = color
    return this
  }

  /**
   * 设置是否支持水波纹效果--5.0及以上
   *
   * @param enable
   * @return
   */
  fun setRippleEnable(enable: Boolean): RadiusViewDelegate {
    mRippleEnable = enable
    return this
  }

  /**
   * 设置选中状态变换监听
   *
   * @param listener
   * @return
   */
  fun setOnSelectedChangeListener(listener: OnSelectedChangeListener?): RadiusViewDelegate {
    mOnSelectedChangeListener = listener
    return this
  }

  /**
   * @param selected
   */
  fun setSelected(selected: Boolean) {
    if (mView != null) {
      if (mSelected != selected) {
        mSelected = selected
        if (mOnSelectedChangeListener != null) {
          mOnSelectedChangeListener!!.onSelectedChanged(mView, mSelected)
        }
      }
    }
    init()
  }

  /**
   * 设置状态切换延时
   *
   * @param duration
   * @return
   */
  fun setEnterFadeDuration(duration: Int): RadiusViewDelegate {
    if (duration >= 0) {
      mEnterFadeDuration = duration
    }
    return this
  }

  /**
   * 设置状态切换延时
   *
   * @param duration
   * @return
   */
  fun setExitFadeDuration(duration: Int): RadiusViewDelegate {
    if (duration > 0) {
      mExitFadeDuration = duration
    }
    return this
  }

  /**
   * 设置 背景Drawable颜色线框色及圆角值
   *
   * @param gd
   * @param color
   * @param strokeColor
   */
  private fun setDrawable(gd: GradientDrawable, color: Int, strokeColor: Int) {
    //任意值大于0执行
    if (mTopLeftRadius > 0 || mTopRightRadius > 0 || mBottomRightRadius > 0 || mBottomLeftRadius > 0) {
      mRadiusArr[0] = mTopLeftRadius
      mRadiusArr[1] = mTopLeftRadius
      mRadiusArr[2] = mTopRightRadius
      mRadiusArr[3] = mTopRightRadius
      mRadiusArr[4] = mBottomRightRadius
      mRadiusArr[5] = mBottomRightRadius
      mRadiusArr[6] = mBottomLeftRadius
      mRadiusArr[7] = mBottomLeftRadius
      gd.cornerRadii = mRadiusArr
    } else {
      gd.cornerRadius = radius
    }
    gd.setStroke(mStrokeWidth, strokeColor, mStrokeDashWidth, mStrokeDashGap)
    gd.setColor(color)
  }

  /**
   * 设置shape属性
   * 设置完所有属性后调用设置背景
   */
  open fun init() {
    //获取view当前drawable--用于判断是否通过默认属性设置背景
    val mDrawable = mView!!.background
    //判断是否使用自定义颜色值
    val isSetBg =
      mBackgroundColor != Int.MAX_VALUE
          || mBackgroundPressedColor != Int.MAX_VALUE
          || mBackgroundDisabledColor != Int.MAX_VALUE
          || mBackgroundSelectedColor != Int.MAX_VALUE
          || mStrokeWidth > 0
          || radius > 0
          || mTopLeftRadius > 0
          || mTopLeftRadius > 0
          || mBottomLeftRadius > 0
          || mBottomRightRadius > 0
    setDrawable(mBackgroundChecked, mBackgroundCheckedColor, mStrokeCheckedColor)
    setDrawable(mBackgroundSelected, mBackgroundPressedColor, mStrokeSelectedColor)
    setDrawable(mBackground, mBackgroundColor, mStrokeColor)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
      && mRippleEnable && mView!!.isEnabled && !mView!!.isSelected
    ) { //5.0以上且设置水波属性并且可操作
      val rippleDrawable = RippleDrawable(
        ColorStateList(
          arrayOf(intArrayOf(mStatePressed), intArrayOf()), intArrayOf(
            if (mRippleColor != Int.MAX_VALUE) mRippleColor else mBackgroundPressedColor,
            mRippleColor
          )
        ), getContentDrawable(mDrawable, isSetBg), null
      )
      mView!!.background = rippleDrawable
    } else {
      if (!isSetBg) {
        return
      }
      mStateDrawable.setEnterFadeDuration(mEnterFadeDuration)
      mStateDrawable.setExitFadeDuration(mExitFadeDuration)
      if (mBackgroundPressedColor != Int.MAX_VALUE || mStrokePressedColor != Int.MAX_VALUE) {
        setDrawable(mBackgroundPressed, mBackgroundPressedColor, mStrokePressedColor)
        mStateDrawable.addState(intArrayOf(mStatePressed), mBackgroundPressed)
      }
      if (mBackgroundSelectedColor != Int.MAX_VALUE || mStrokeSelectedColor != Int.MAX_VALUE) {
        setDrawable(mBackgroundSelected, mBackgroundSelectedColor, mStrokeSelectedColor)
        mStateDrawable.addState(intArrayOf(mStateSelected), mBackgroundSelected)
      }
      if (mBackgroundCheckedColor != Int.MAX_VALUE || mStrokeCheckedColor != Int.MAX_VALUE) {
        setDrawable(mBackgroundChecked, mBackgroundCheckedColor, mStrokeCheckedColor)
        mStateDrawable.addState(intArrayOf(mStateChecked), mBackgroundChecked)
      }
      if (mBackgroundDisabledColor != Int.MAX_VALUE || mStrokeDisabledColor != Int.MAX_VALUE) {
        setDrawable(mBackgroundDisabled, mBackgroundDisabledColor, mStrokeDisabledColor)
        mStateDrawable.addState(intArrayOf(mStateDisabled), mBackgroundDisabled)
      }
      mStateDrawable.addState(intArrayOf(), mBackground) //默认状态--放置在最后否则其它状态不生效
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        mView!!.background = mStateDrawable
      } else {
        mView!!.setBackgroundDrawable(mStateDrawable)
      }
    }
    return
  }

  /**
   * 水波纹效果完成后最终展示的背景Drawable
   *
   * @param mDrawable
   * @param isSetBg
   * @return
   */
  private fun getContentDrawable(mDrawable: Drawable?, isSetBg: Boolean): Drawable? {
    if (mView is CompoundButton) {
      return if (!isSetBg)
        mDrawable
      else if ((mView as CompoundButton).isChecked)
        mBackgroundChecked
      else if (mView!!.isSelected)
        mBackgroundSelected
      else mBackground
    }

    return if (!isSetBg) mDrawable
    else if (mView!!.isSelected)
      mBackgroundSelected
    else
      mBackground
  }
}